package com.catena.mock.node;

import com.catena.core.node.CatenaNode;
import com.catena.mock.MockRuntimeException;
import com.catena.mock.core.HttpRequestMethod;
import com.catena.mock.core.ScanContext;
import com.catena.mock.core.ScanProjectContext;
import com.catena.mock.param.MockBaseParam;
import com.catena.response.MockReturnResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Created by hx-pc on 16-5-20.
 */
public class MockManageNode extends CatenaNode {

    private static final Logger LOGGER =LoggerFactory.getLogger(MockManageNode.class);
    private static final String API_STR = "apiStr";
    private static final String DATA_STR = "dataStr";
    private static final String CONTENT_STR = "contentStr";
    private static final String REQUEST_ERROR = "请求方式错误";

    public void addMock(MockBaseParam mockBaseParam) {
        String apiStr = "\n" + getBean(ScanProjectContext.class).getEnvironmentMap().get(ScanProjectContext.API_KEY) + "." + mockBaseParam.getKey() + "=" + mockBaseParam.getApiValue() + "\n";
        String dataStr = getBean(ScanProjectContext.class).getEnvironmentMap().get(getDataKey(mockBaseParam.getHttpRequestMethod())) + "." + mockBaseParam.getKey() + "=" + mockBaseParam.getDataValue() + "\n";
        String contentStr = getBean(ScanProjectContext.class).getEnvironmentMap().get(getContentKey(mockBaseParam.getHttpRequestMethod())) + "." + mockBaseParam.getKey() + "=" + mockBaseParam.getContent() + "\n";
        mockBaseParam.getOtherParam().put(API_STR, apiStr.getBytes());
        mockBaseParam.getOtherParam().put(DATA_STR, dataStr.getBytes());
        mockBaseParam.getOtherParam().put(CONTENT_STR, contentStr.getBytes());
    }

    public void writerMockFile(MockBaseParam mockBaseParam) throws IOException {
        File file = new File(getBean(ScanProjectContext.class).getScanContext(mockBaseParam.acceptServletRequest().getHeader("project")).getFileName());
        if (!file.exists()) {
            throw new MockRuntimeException(402, "mockConfig.properties 不存在");
        }
        FileOutputStream fos = new FileOutputStream(file, true);
        fos.write((byte[]) mockBaseParam.getOtherParam().get(API_STR));
        fos.write((byte[]) mockBaseParam.getOtherParam().get(DATA_STR));
        fos.write((byte[]) mockBaseParam.getOtherParam().get(CONTENT_STR));
        fos.close();
    }

    private String getDataKey(HttpRequestMethod httpRequestMethod) {
        if (httpRequestMethod == HttpRequestMethod.GET) {
            return ScanProjectContext.DATA_GET_KEY;
        } else if (httpRequestMethod == HttpRequestMethod.POST) {
            return ScanProjectContext.DATA_POST_KEY;
        } else if (httpRequestMethod == HttpRequestMethod.PUT) {
            return ScanProjectContext.DATA_PUT_KEY;
        } else if (httpRequestMethod == HttpRequestMethod.DELETE) {
            return ScanProjectContext.DATA_DELETE_KEY;
        } else {
            throw new MockRuntimeException(402, REQUEST_ERROR);
        }
    }

    private String getContentKey(HttpRequestMethod httpRequestMethod) {
        if (httpRequestMethod == HttpRequestMethod.GET) {
            return ScanProjectContext.DATA_CONTENT_GET_KEY;
        } else if (httpRequestMethod == HttpRequestMethod.POST) {
            return ScanProjectContext.DATA_CONTENT_POST_KEY;
        } else if (httpRequestMethod == HttpRequestMethod.PUT) {
            return ScanProjectContext.DATA_CONTENT_PUT_KEY;
        } else if (httpRequestMethod == HttpRequestMethod.DELETE) {
            return ScanProjectContext.DATA_CONTENT_DELETE_KEY;
        } else {
            throw new MockRuntimeException(402, REQUEST_ERROR);
        }
    }

    public void getMockList(MockBaseParam mockBaseParam) throws IOException {
        getBean(ScanProjectContext.class).getScanContext(mockBaseParam.acceptServletRequest().getParameter("project")).checkScanMockData();
        Map<String, String> returnList = new HashMap<>();
        String project = mockBaseParam.acceptServletRequest().getParameter("project");
        mockBaseParam.setHttpRequestMethod(getHttpRequestMethod(mockBaseParam.acceptServletRequest().getAttribute("httpRequestMethod").toString()));
        Map<String, String> map = getResourceData(mockBaseParam.getHttpRequestMethod(), project);
        List<MockReturnResponse> list = new CopyOnWriteArrayList<>();
        map.keySet().forEach(str -> getBean(ScanProjectContext.class).getScanContext(project).getAllKeyUrl()
                .forEach(entry -> {
                    if (entry.getValue().equals(str)) {
                        returnList.put(entry.getKey().toString(), str);
                        list.add(MockReturnResponse.build(entry.getKey().toString(), str));
                    }
                }));
        mockBaseParam.setData(list);
    }

    private HttpRequestMethod getHttpRequestMethod(String method) {
        if (method.equalsIgnoreCase(HttpRequestMethod.GET.name())) {
            return HttpRequestMethod.GET;
        } else if (method.equalsIgnoreCase(HttpRequestMethod.POST.name())) {
            return HttpRequestMethod.POST;
        } else if (method.equalsIgnoreCase(HttpRequestMethod.PUT.name())) {
            return HttpRequestMethod.PUT;
        } else if (method.equalsIgnoreCase(HttpRequestMethod.DELETE.name())) {
            return HttpRequestMethod.DELETE;
        } else {
            throw new MockRuntimeException(402, REQUEST_ERROR);
        }
    }


    private Map<String, String> getResourceData(HttpRequestMethod httpRequestMethod, String project) {
        return getBean(ScanProjectContext.class).getScanContext(project).getResourceDataMap().get(httpRequestMethod.name());
    }

    public void returnData(MockBaseParam mockBaseParam) {
        mockBaseParam.setData(mockBaseParam.acceptServletRequest().getAttribute("data"));
    }

    public void addProject(MockBaseParam mockBaseParam) {
        try {
            getBean(ScanProjectContext.class).addProject(mockBaseParam.getOtherParam().get("project").toString());
        } catch (IOException e) {
            LOGGER.error("{}", "添加工程失败." + e);
            throw new MockRuntimeException(406, "添加工程失败");
        }
    }

    public void deleteProject(MockBaseParam mockBaseParam) {
        try {
            getBean(ScanProjectContext.class).deleteProject(mockBaseParam.getOtherParam().get("project").toString());
        } catch (IOException e) {
            LOGGER.error("{}", "删除工程失败." + e);
            throw new MockRuntimeException(406, "删除工程失败");
        }
    }

    public void projectContextReset() throws IOException {
        getBean(ScanProjectContext.class).reset();
    }
}
